import { downloadFile } from '@/utils'
import Axios from 'axios'
import Vue from 'vue'

const state = {
  downLoadList: []
}
const actions = {
  addPlayList(context, playList) {
    let hasMore = true
    let tmp = []

    function getSongList() {
      if (!hasMore) {
        merge()
        reset()
        context.dispatch('downLoadStart')
        return
      }
      pageSize
      playList.getSongList({
        pageNum,
        pageSize
      }).then(songList => {
        if (songList.length === 0) {
          hasMore = false
        }
        tmp.push(...songList)
        pageNum++
        getSongList()
      })
    }
    function merge() {
      let downLoadList = context.state.downLoadList
      let ft = tmp.filter(item => !downLoadList.some(it => item.id === it.id))
      context.state.downLoadList.push(...ft)
    }
    getSongList()
  },
  addSingleSong(context, song) {
    context.state.downLoadList.push(song)
    context.dispatch('downLoadStart')
  },
  downLoadStart() {
    let _this = this
    function loopDown() {
      downLoadSong.call(_this).then(res => {
        if (res !== 'done') {
          index++
          loopDown()
        } else {
          index = 0
        }
      }).catch(e => {
        if (!e.cancel) {
          index++
          loopDown()
        }
      })
    }
    loopDown()
  }
}
const mutations = {
  startAll(state) {
    index = 0
    state.downLoadList.forEach(item => {
      if (item.downLoadState === 'pause' || item.downLoadState === 'fail') {
        item.downLoadState = null
      }
    })
    this.dispatch('downloadMgt/downLoadStart')
  },
  pauseAll(state) {
    if (typeof cancel === 'function') {
      cancel('cancel request')
    }
    state.downLoadList.forEach(item => {
      if (!item.downLoadState) {
        item.downLoadState = 'pause'
      }
    })
  },
  deleteAll(state) {
    index = 0
    if (typeof cancel === 'function') {
      cancel('cancel request')
    }
    state.downLoadList = []
  },
  startSinger(state, song) {
    if (typeof cancel === 'function') {
      cancel('cancel request')
    }

    let index_bak = index
    index = state.downLoadList.findIndex(item => item.id === song.id)

    let _song = state.downLoadList[index]
    _song.downLoadState = null

    downLoadSong.call(this).then(() => {
      index = index_bak
    }).catch(e => {
      _song.downLoadState = e.cancel ? 'pause' : 'fail'
      Vue.set(state.downLoadList, index, _song)
    })
  }
}
const getters = {
  downLoadList() {
    return state.downLoadList
  }
}

let pageNum = 1
let pageSize = 100
function reset() {
  pageNum = 1
  pageSize = 100
}

let index = 0
let CancelToken = Axios.CancelToken
let cancel
function downLoadSong() {
  let song = this.state.downloadMgt.downLoadList[index]

  if (!song) {
    return Promise.resolve('done')
  }

  if (song.downLoadState === 'success') {
    return Promise.resolve(song)
  }

  if (!song.url) {
    song.percentage = 0
    song.downLoadState = 'fail'
    Vue.set(this.state.downloadMgt.downLoadList, index, song)
    return Promise.resolve(song)
  }

  let url = song.url
  let suffix = url.substr(url.lastIndexOf('.'), url.length)
  let _state = this.state

  return new Promise((resolve, reject) => {
    downloadFile(song.url, `${song.name}${suffix}`, {
      onDownloadProgress (progress) {
        song.percentage = Math.round(progress.loaded / progress.total * 100)
        if (song.percentage === 100) {
          song.downLoadState = 'success'
          song.percentage = 0
          Vue.set(_state.downloadMgt.downLoadList, index, song)
          resolve(song)
        }
      },
      cancelToken: new CancelToken(function executor(c) {
        cancel = c
      })
    }).catch(e => {
      song.percentage = 0
      if (!e.cancel) {
        song.downLoadState = 'fail'
        Vue.set(_state.downloadMgt.downLoadList, index, song)
      }
      reject(e)        
    })
  })
}

export default {
  namespaced: true,
  state,
  actions,
  mutations,
  getters
}